. ./logging.sh

REGISTRY_BASE='https://registry-1.docker.io'
AUTH_SERVICE='registry.docker.io'
AUTH_BASE='https://auth.docker.io'

get_token() {
	local image="$1"; shift

	log INFO "Getting Token..."
	local token="$(
		curl -fsSL "$AUTH_BASE/token?service=$AUTH_SERVICE&scope=repository:$image:pull" \
			| jq --raw-output '.token' \
	)"
	success "$token"

	echo "$token"
}

fetch_manifest() {
	local token="$1"; shift
	local image="$1"; shift
	local digest="$1"; shift

	log INFO "Getting Manifest..."
	local manifest="$(
	 	curl -fsSL \
			-H "Authorization: Bearer $token" \
			-H 'Accept: application/vnd.docker.distribution.manifest.v2+json' \
			"$REGISTRY_BASE/v2/$image/manifests/$digest" \
		)"
	success "$token"

	echo "$manifest"
}

fetch_stuff() {
	local token="$1"; shift
	local image="$1"; shift
	local digest="$1"; shift
	local target="$1"; shift
	local curlprogress="$1"; shift

	log INFO "Fetching header..."
	local header="$( \
		curl -sS \
			-H "Authorization: Bearer $token" \
			"$REGISTRY_BASE/v2/$image/blobs/$digest" \
			-o "$target" \
			-D- \
	)"
	success "$header"
	header="$(echo "$header" | tr -d '\r')"

	printf '%s' "$header" > headerfile
	if grep -qE "^HTTP/[0-9].[0-9] 3" < headerfile; then
		rm -f "$target"

		local redirect="$(echo "$header" \
			| awk -F ': ' 'match(tolower($0),/location/) { f=NR } f&&NR-1==f' RS=": " \
			| sed 's/Date//')"
		if [ -z "$redirect" ]; then
			log ERROR "Could not fetch $image"
			log ERROR "$header" | head -1 >&2
			return 1
		fi

		if [ $curlprogress = '-#' ] || [ $curlprogress = '--progress' ]; then
			log INFO "Fetching file:\n"
		else
			log INFO "Fetching file..."
		fi
		mkdir -p "$(dirname target)"
		curl -fSL ${curlprogress} "$redirect" -o "$target"
		if [ $curlprogress = '-#' ] || [ $curlprogress = '--progress' ]; then
			printf ''
		else
			success "$(cat $target)"
		fi

		rm ./headerfile
	else
		if grep -qE "^HTTP/[0-9].[0-9] 404" < headerfile; then
			log ERROR "404: Likely no network!"
			exit 1
		else
			log ERROR "Invalid Header! Check ./headerfile"
			exit 1
		fi
	fi
}

handle_manifest_v2() {
	local token="$1"; shift
	local image="$1"; shift
	local tag="$1"; shift
	local dir="$1"; shift
	local manifest="$1"; shift

#	log INFO "Analysing Manifest:\n"
	local config_digest="$(echo "$manifest" \
		| jq --raw-output '.config.digest')"
	local image_id="$(echo $config_digest | cut -f2 -d':')"
	log OPTINFO "Image Id: $image_id\n"
	fetch_stuff "$token" "$image" "$config_digest" "$dir/$image/$tag.json" ' -s'

	#THIS IS NOT COMPATIBLE WITH DOCKER!!!
	jq -cr ". + {\"pulled\": \"$(date +%Y-%m-%d)\"}" "$dir/$image/$tag.json" > "$dir/$image/$tag.json.tmp" && mv "$dir/$image/$tag.json.tmp" "$dir/$image/$tag.json"
	#!!!

	local layer_fs="$(echo "$manifest" | jq --raw-output --compact-output '.layers[]')"
	log OPTINFO "Found $(echo $layer_fs | wc --words ) filelayers.\n"

	log INFO "Downloading $image\n"
	set -- $layer_fs

	log INFO "$(printf '%s %s %s' 'SKIP' 'NUM' 'DIGEST')\n"
	local layernum=0
	local layer_id=''
	#TODO: Add protection for multi download.
	if ! $ASK; then
		rm -rf "$dir/$image/$tag"
	elif [ -d "$dir/$image/$tag" ]; then
		log INFO "Image $image/$tag will be removed [y/n]: "
		read askresult
		case "$askresult" in
			y|Y|yes|YES|Yes)
				rm -rf "$dir/$image/$tag"
				;;
			*)
				exit 0
				;;
		esac
	fi

	for i in "$@"; do
		local layer_type="$(echo "$1" | jq --raw-output '.mediaType')"
		local layer_digest="$(echo "$1" | jq --raw-output '.digest')"
		local parent_id="$layer_id"
		layer_id="$(echo "$parent_id"$'\n'"$layer_digest" \
			| sha256sum \
			|cut -f1 -d' ' \
		)"

		mkdir -p "$dir/$image/$tag/$layer_id"
		echo "1.0" > "$dir/$image/$tag/$layer_id/VERSION"

		#TODO: Add Json handling

		case "$layer_type" in
			application/vnd.docker.image.rootfs.diff.tar.gzip)
				local layer_tar="$layer_id/layer.tar.gz"
				#TODO: Add to file log.

				if [ -f "$dir/$image/$tag/$layer_tar" ]; then
					log WARNING "$(printf '%4s %03d %64s' \
						"YES" "$layernum" "$(echo $layer_digest \
						| cut -f2 -d':')")\n"
					layernum="$(expr $layernum + 1)"
					continue
				fi

				log SUCCESS "$(printf '%4s %03d %64s' \
					"NO" "$layernum" "$(echo $layer_digest \
					| cut -f2 -d':')")\n"
				fetch_stuff "$token" "$image" "$layer_digest" "$dir/$image/$tag/$layer_tar"	-#
				layernum="$(expr $layernum + 1)"
				;;
			*)
				log ERROR "Unknown layer type ($image):\n\t$layer_type"
				exit 1
				;;
		esac

		shift
	done
}

